//
//  ECFilePathUtility.m
//  ECCoreLibrary
//
//  Created by Matt Austin on 4/29/14.
//  Copyright (c) 2014 EnglishCentral, Inc. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "MujiDubFilePathUtility.h"

static NSString * const kUserAudioDirectoryName  = @"UserAudio/";
static NSString * const kUserCachesDirectoryName = @"com.englishcentral.cache/";
static NSString * const kOggDirectoryName        = @"Ogg/";
static NSString * const kUserAudioMP3DirectoryName  = @"UserAudioMP3/";


@interface MujiDubFilePathUtility ()

@property (nonatomic, readwrite, copy) NSMutableDictionary *mutablePaths;

@end


@implementation MujiDubFilePathUtility

#pragma mark -
#pragma mark Getters and Setters

- (NSMutableDictionary *)mutablePaths
{
   if (!_mutablePaths)
   {
      _mutablePaths = [[NSMutableDictionary alloc] initWithCapacity:4];
      
      NSFileManager *fileManager = [NSFileManager defaultManager];
      NSError *outError = nil;
      
      NSString *userCachesDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
      userCachesDirectory = [userCachesDirectory stringByAppendingPathComponent:kUserCachesDirectoryName];
      if ([fileManager fileExistsAtPath:userCachesDirectory])
      {
         [_mutablePaths setObject:userCachesDirectory forKey:@(MujiDubFilePathDirectoryUserCaches)];
      }
      else
      {
         if ([fileManager createDirectoryAtPath:userCachesDirectory withIntermediateDirectories:YES attributes:nil error:&outError])
         {
            [_mutablePaths setObject:userCachesDirectory forKey:@(MujiDubFilePathDirectoryUserCaches)];
         }
      }
      
      
      NSString *userDocumentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
      [_mutablePaths setObject:userDocumentsDirectory forKey:@(MujiDubFilePathDirectoryUserDocument)];
      
      NSString *userAudio = [userDocumentsDirectory stringByAppendingPathComponent:kUserAudioDirectoryName];
      if ([fileManager fileExistsAtPath:userAudio])
      {
         [_mutablePaths setObject:userAudio forKey:@(MujiDubFilePathDirectoryUserAudio)];
      }
      else
      {
         if ([fileManager createDirectoryAtPath:userAudio withIntermediateDirectories:YES attributes:nil error:&outError])
         {
            [_mutablePaths setObject:userAudio forKey:@(MujiDubFilePathDirectoryUserAudio)];
         }
      }

       NSString *userAudioMP3 = [userDocumentsDirectory stringByAppendingPathComponent:kUserAudioMP3DirectoryName];
       if ([fileManager fileExistsAtPath:userAudioMP3])
       {
           [_mutablePaths setObject:userAudioMP3 forKey:@(MujiDubFilePathDirectoryUserAudioMP3)];
       }
       else
       {
           if ([fileManager createDirectoryAtPath:userAudioMP3 withIntermediateDirectories:YES attributes:nil error:&outError])
           {
               [_mutablePaths setObject:userAudioMP3 forKey:@(MujiDubFilePathDirectoryUserAudioMP3)];
           }
       }

       
      NSString *oggDirectory = [userCachesDirectory stringByAppendingPathComponent:kOggDirectoryName];
      if ([fileManager fileExistsAtPath:oggDirectory])
      {
         [_mutablePaths setObject:oggDirectory forKey:@(MujiDubFilePathDirectoryUserOgg)];
      }
      else
      {
         if ([fileManager createDirectoryAtPath:oggDirectory withIntermediateDirectories:YES attributes:nil error:&outError])
         {
            [_mutablePaths setObject:oggDirectory forKey:@(MujiDubFilePathDirectoryUserOgg)];
         }
      }
   }

   return _mutablePaths;
}


#pragma mark -
#pragma mark Singleton Access

+ (id)sharedUtility
{
   static MujiDubFilePathUtility *_sharedUtility = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^
   {
      _sharedUtility = [[MujiDubFilePathUtility alloc] init];
   });
   
   return _sharedUtility;
}

#pragma mark -
#pragma mark Initializers

- (id)init
{
   self = [super init];
   if (self)
   {
      NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
      
      [defaultCenter addObserver:self
                        selector:@selector(didReceiveMemoryWarningNotification:)
                            name:UIApplicationDidReceiveMemoryWarningNotification
                          object:nil];
   }
   
   return self;
}


#pragma mark -
#pragma mark NSObject

- (void)dealloc
{
   NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
   
   [defaultCenter removeObserver:self
                            name:UIApplicationDidReceiveMemoryWarningNotification
                          object:nil];
}



#pragma mark -
#pragma mark Public Methods

- (NSString *)getPathOfDirectory:(MujiDubFilePathDirectory)directory
{
   return [[self mutablePaths] objectForKey:@(directory)];
}


- (BOOL)fileExistsAtPath:(NSString *)path
{
   return [[NSFileManager defaultManager] fileExistsAtPath:path];
}


- (BOOL)createFileWithPath:(NSString *)path
              withContents:(NSData *)contents
                attributes:(NSDictionary *)attributes
        overWriteAnyCached:(BOOL)overWriteAnyCached
{
   if (!path)
   {
      return NO;
   }
   
   NSString *key = [path lastPathComponent];
   if (overWriteAnyCached || ![[self mutablePaths] objectForKey:key])
   {
      if (overWriteAnyCached || ![self fileExistsAtPath:path])
      {
         if (![[NSFileManager defaultManager] createFileAtPath:path
                                                      contents:contents
                                                    attributes:attributes])
         {
            return NO;
         }
      }
      
      [[self mutablePaths] setObject:path forKey:key];
   }
   
   return YES;
}

- (NSString *)createFileWithPathComponent:(NSString *)pathComponent
                              inDirectory:(MujiDubFilePathDirectory)directory
                              withContent:(NSData *)content
                               attributes:(NSDictionary *)attributes
                       overWriteAnyCached:(BOOL)overWriteAnyCached
{
   if (!pathComponent)
   {
      return nil;
   }
   
   NSString *filePath = [[self mutablePaths] objectForKey:pathComponent];
   if (overWriteAnyCached || !filePath)
   {
      filePath = [self getPathOfDirectory:directory];
      filePath = [filePath stringByAppendingPathComponent:pathComponent];
      
      if (![self createFileWithPath:filePath
                       withContents:content
                         attributes:attributes
                 overWriteAnyCached:overWriteAnyCached])
      {
         return nil;
      }
   }
   
   return filePath;
}

- (BOOL)removeFileWithPathComponent:(NSString *)pathComponent
                        inDirectory:(MujiDubFilePathDirectory)directory
                              error:(NSError **)outError
{
   if (!pathComponent)
   {
      return NO;
   }
   
   NSString *filePath = [[self mutablePaths] objectForKey:pathComponent];
   
   if (!filePath)
   {
      NSString *directoryPath = [self getPathOfDirectory:directory];
      filePath = [directoryPath stringByAppendingPathComponent:pathComponent];
   }
   
   return [self removeFileWithPath:filePath error:&*outError];
}


- (BOOL)removeFileWithPath:(NSString *)path error:(NSError **)outError
{
   if (!path)
   {
      return NO;
   }
   
   NSString *key = [path lastPathComponent];
   NSString *filePath = [[self mutablePaths] objectForKey:key];
   
   if (!filePath)
   {
      filePath = path;
   }
   
   [[self mutablePaths] removeObjectForKey:key];
   return [[NSFileManager defaultManager] removeItemAtPath:filePath error:&*outError];
}


#pragma mark -
#pragma mark NSNotification Helpers

- (void)didReceiveMemoryWarningNotification:(NSNotification *)notification
{
   [self setMutablePaths:nil];
}

@end
